﻿using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;

namespace UFrame
{
    public class CaptureScreenTool
    {
        /// <summary>
        /// 自定义截图的大小（包括UI）
        /// </summary>
        /// <returns>The screen.</returns>
        /// <param name="rect">Rect.</param>
        public static IEnumerator CaptureScreen(Rect rect, Action<Texture2D> callback)
        {
            Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
            yield return new WaitForEndOfFrame();

            screenShot.ReadPixels(rect, 0, 0);

            screenShot.Apply();

            if (callback != null)
            {
                Debug.Log("----> CaptureScreen callback ");
                callback(screenShot);
            }
        }

        public static IEnumerator CaptureScreenByCamera(Camera camera, Action<Texture2D> callback)
        {
            Rect rect = new Rect();
            rect.width = Screen.width;
            rect.height = Screen.height;
            RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0);

            camera.targetTexture = rt;
            camera.Render();

            RenderTexture.active = rt;
            Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);

            screenShot.ReadPixels(rect, 0, 0);
            screenShot.Apply();

            camera.targetTexture = null;
            RenderTexture.active = null;
            GameObject.Destroy(rt);
            yield return new WaitForEndOfFrame();

            if (callback != null)
            {
                Debug.Log("----> CaptureScreen callback ");
                callback(screenShot);
            }
        }

        /// <summary>
        /// 自定义截图的大小 保存（包括UI）
        /// </summary>
        /// <returns>The screen.</returns>
        /// <param name="rect">Rect.</param>
        public static IEnumerator CaptureScreenSave(Rect rect, Action<Texture2D> callback)
        {
            Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
            yield return new WaitForEndOfFrame();

            screenShot.ReadPixels(rect, 0, 0);

            screenShot.Apply();

            byte[] bytes = screenShot.EncodeToPNG();
            string filename = string.Empty;
#if UNITY_IPHONE || UNITY_IOS || UNITY_ANDROID || UNITY_EDITOR
            filename = Application.persistentDataPath + "/ScreenShot.png";
#endif
            File.WriteAllBytes(filename, bytes);

            bool bHave = false;
            yield return new WaitUntil(() =>
            {
                bHave = File.Exists(filename);
                return bHave;
            });
            // 调用SDK
            if (bHave == false)
            {
                Debug.Log("----> 截屏出错！");
            }
            else
            {
                if (callback != null)
                {
                    Debug.Log("----> GetCapture callback ");
                    callback(screenShot);
                }
            }
        }

        /// <summary>
        /// 下载图片
        /// </summary>
        /// <param name="rect">Rect.</param>
        /// <param name="url">URL.</param>
        /// <param name="callback">Callback.</param>
        public static IEnumerator GetDownLoadImage(Rect rect, string url, Action<Texture2D> callback)
        {
            UnityWebRequest www = new UnityWebRequest(url);
            yield return www;

            if (www.isDone && www.error == null)
            {
                Texture2D texture = new Texture2D(80, 80);
                texture.LoadImage(www.downloadHandler.data);

                //tempImage = www.texture;
                if (callback != null)
                {
                    yield return new WaitForEndOfFrame();
                    Debug.Log("---> texture.width " + texture.width + " texture.height " + texture.height + " url " +
                              url);
                    callback(texture);
                }
            }
        }

        /// <summary> 双线性插值法缩放图片，等比缩放</summary>
        public static Texture2D ScaleTextureBilinear(Texture2D originalTexture, float scaleFactor)
        {
            Texture2D newTexture = new Texture2D(Mathf.CeilToInt(originalTexture.width * scaleFactor),
                Mathf.CeilToInt(originalTexture.height * scaleFactor));
            float scale = 1.0f / scaleFactor;
            int maxX = originalTexture.width - 1;
            int maxY = originalTexture.height - 1;
            for (int y = 0; y < newTexture.height; y++)
            {
                for (int x = 0; x < newTexture.width; x++)
                {
                    // Bilinear Interpolation  
                    float targetX = x * scale;
                    float targetY = y * scale;
                    int x1 = Mathf.Min(maxX, Mathf.FloorToInt(targetX));
                    int y1 = Mathf.Min(maxY, Mathf.FloorToInt(targetY));
                    int x2 = Mathf.Min(maxX, x1 + 1);
                    int y2 = Mathf.Min(maxY, y1 + 1);

                    float u = targetX - x1;
                    float v = targetY - y1;
                    float w1 = (1 - u) * (1 - v);
                    float w2 = u * (1 - v);
                    float w3 = (1 - u) * v;
                    float w4 = u * v;
                    Color color1 = originalTexture.GetPixel(x1, y1);
                    Color color2 = originalTexture.GetPixel(x2, y1);
                    Color color3 = originalTexture.GetPixel(x1, y2);
                    Color color4 = originalTexture.GetPixel(x2, y2);
                    Color color = new Color(
                        Mathf.Clamp01(color1.r * w1 + color2.r * w2 + color3.r * w3 + color4.r * w4),
                        Mathf.Clamp01(color1.g * w1 + color2.g * w2 + color3.g * w3 + color4.g * w4),
                        Mathf.Clamp01(color1.b * w1 + color2.b * w2 + color3.b * w3 + color4.b * w4),
                        Mathf.Clamp01(color1.a * w1 + color2.a * w2 + color3.a * w3 + color4.a * w4)
                    );
                    newTexture.SetPixel(x, y, color);
                }
            }

            newTexture.Apply();
            return newTexture;
        }

        /// <summary>将图片缩放为指定尺寸</summary>
        public static Texture2D SizeTextureBilinear(Texture2D originalTexture, Vector2 size)
        {
            Texture2D newTexture = new Texture2D(Mathf.CeilToInt(size.x), Mathf.CeilToInt(size.y));
            float scaleX = originalTexture.width / size.x;
            float scaleY = originalTexture.height / size.y;
            int maxX = originalTexture.width - 1;
            int maxY = originalTexture.height - 1;
            for (int y = 0; y < newTexture.height; y++)
            {
                for (int x = 0; x < newTexture.width; x++)
                {
                    float targetX = x * scaleX;
                    float targetY = y * scaleY;
                    int x1 = Mathf.Min(maxX, Mathf.FloorToInt(targetX));
                    int y1 = Mathf.Min(maxY, Mathf.FloorToInt(targetY));
                    int x2 = Mathf.Min(maxX, x1 + 1);
                    int y2 = Mathf.Min(maxY, y1 + 1);

                    float u = targetX - x1;
                    float v = targetY - y1;
                    float w1 = (1 - u) * (1 - v);
                    float w2 = u * (1 - v);
                    float w3 = (1 - u) * v;
                    float w4 = u * v;
                    Color color1 = originalTexture.GetPixel(x1, y1);
                    Color color2 = originalTexture.GetPixel(x2, y1);
                    Color color3 = originalTexture.GetPixel(x1, y2);
                    Color color4 = originalTexture.GetPixel(x2, y2);
                    Color color = new Color(
                        Mathf.Clamp01(color1.r * w1 + color2.r * w2 + color3.r * w3 + color4.r * w4),
                        Mathf.Clamp01(color1.g * w1 + color2.g * w2 + color3.g * w3 + color4.g * w4),
                        Mathf.Clamp01(color1.b * w1 + color2.b * w2 + color3.b * w3 + color4.b * w4),
                        Mathf.Clamp01(color1.a * w1 + color2.a * w2 + color3.a * w3 + color4.a * w4)
                    );
                    newTexture.SetPixel(x, y, color);
                }
            }

            newTexture.Apply();
            return newTexture;
        }
    }
}